package com.nave;

import nave.Constants;
import nave.control.Simulation;
import nave.control.ViewActions;
import nave.model.Spaceship;
import nave.model.Stage;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.Display;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.EditText;

import com.nave.utils.Database;
import com.nave.utils.SoundController;
import com.nave.view.GameView;

public class GameActivity extends Activity implements Runnable, OnClickListener
{
	/*
	 * Attributes
	 */
	private static int FPS = 35;
	private Handler handler;
	private Simulation simulation;

//	private GLSurfaceView naveGLView; // TODO openGL

    private boolean paused;
    private int stageType = Stage.STAGES_RANDOM;

	private ViewActions effects = new ViewActions()
	{
		private static final int VIBRATING_TIME = 200; // in milliseconds
		
		@Override
		public void shot()
		{	
			Context c = GameView.getReference().getContext();

			SoundController.getReference().
			playSound(SoundController.SHOT, c);

		}
		@Override
		public void nextStage()
		{
			Context c = GameView.getReference().getContext();

			SoundController.getReference().pauseBackgroundSound();
			SoundController.getReference().playSound(SoundController.VICTORY, c);

			SoundController.getReference().resumeBackgroundSound();
		}
		@Override
		public void explosion()
		{
			Context c = GameView.getReference().getContext();

			SoundController.getReference().
			playSound(SoundController.EXPLOSION, c);

			new Thread()
			{
				private final int VIBRATING_DELAY_TIME = 140; // in milliseconds

				public void run()
				{
					try
					{
						Thread.sleep(VIBRATING_DELAY_TIME);
					}
					catch (InterruptedException e) {}

					( (Vibrator)getSystemService(Context.VIBRATOR_SERVICE) )
						.vibrate(VIBRATING_TIME);
				}
			}
			.start();
		}
		@Override
		public void endGame()
		{
			final Context c= GameView.getReference().getContext();
			
			SoundController.getReference().pauseBackgroundSound();

			paused = true;
			
			GameView.getReference().dispose();

			AlertDialog.Builder alert = new AlertDialog.Builder(GameActivity.this);

			alert.setMessage(R.string.nameEntryMessage);

			// Set an EditText view to get user input 
			final EditText input = new EditText(GameActivity.this);
			input.setSingleLine();
			alert.setView(input);

			alert.setPositiveButton("Ok", new DialogInterface.OnClickListener()
			{
				public void onClick(DialogInterface dialog, int whichButton)
				{
					String name = input.getText().toString().trim();
					if( name != null )
					{
						Database db = new Database(GameActivity.this);
						db.open();
						db.insertRecord(name, simulation.score());
						db.close();
					}

					finish();
					
					SoundController.getReference().playSound(SoundController.GAME_OVER, c);
				}
			});
			alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
			{
				public void onClick(DialogInterface dialog, int whichButton)
				{
					dialog.cancel();
					
					finish();
					
					SoundController.getReference().playSound(SoundController.GAME_OVER, c);
				}
			});
			alert.show();
		}
	};
	

	/*
	 * Android functions
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);

		// set the Handler that does the loop
		handler = new Handler();


		// set up the screen resolution
		Constants.STATUS_BAR_WIDTH = 30; // TODO change to TILE_SIZE
		Display display = this.getWindowManager().getDefaultDisplay();
		Constants.SCREEN_HEIGHT = display.getHeight();
		Constants.SCREEN_WIDTH = display.getWidth() - Constants.STATUS_BAR_WIDTH;

		// TODO math to do this automatically,
		// or maybe set by the user...
		Constants.STAGE_COLS = Constants.SCREEN_WIDTH / 30; // TODO change to TILE_SIZE
		Constants.STAGE_ROWS = Constants.SCREEN_HEIGHT / 30;// TODO change to TILE_SIZE
		

		// Gets the stage type passed by the main menu
		Intent it = getIntent();
		if ( it != null )
		{
			stageType = it.getIntExtra("StageType", Stage.STAGES_RANDOM);
		}
		else
			stageType = Stage.STAGES_RANDOM;


		/* Start the GameView */
//		naveGLView = new NaveRenderer(this);
//      setContentView(naveGLView);
		setContentView(R.layout.game);


		/* Set the touch control */
		gestureDetector = new GestureDetector(new GestureControlling());
        gestureListener = new View.OnTouchListener()
        {
            public boolean onTouch(View v, MotionEvent event)
            {
                if (gestureDetector.onTouchEvent(event))
                {
                    return true;
                }
                return false;
            }
        };
        GameView.getReference().setOnTouchListener(gestureListener);
        GameView.getReference().setOnClickListener(this);
	}
	@Override
	protected void onStart()
	{
		super.onStart();

		Simulation.startSimulation(stageType);
		simulation = Simulation.getSimulation();
		simulation.setSimulationFunctions(effects);

		GameView.setObjects( simulation.getObjects() );

		handler.post(this);

		SoundController.getReference().
		playSound(SoundController.TURBINE,
				GameView.getReference().getContext(), -1 );
	}
	@Override
	protected void onPause()
	{
		super.onPause();
		paused = true;
		SoundController.getReference().pauseBackgroundSound();
	}
	@Override
	protected void onResume()
	{
		super.onResume();
		paused = false;
		handler.post(this);
		SoundController.getReference().resumeBackgroundSound();
	}
	@Override
	protected void onStop()
	{
		super.onStop();
		paused = false;

		GameView.getReference().dispose();
		
		finish();
	}
	@Override
	public void onConfigurationChanged(Configuration newConfig)
	{
		super.onConfigurationChanged(newConfig);
		setContentView(R.layout.game);

		GameView.getReference().setOnTouchListener(gestureListener);
        GameView.getReference().setOnClickListener(this);
	}

	/*
	 *	Loop
	 */
	private int sleep = 1000 / FPS;
	int i = 0;
	public void update(float delta)
	{
		simulation.update(delta);
		GameView.getReference().update();
//		StatusBarView.getReference().postInvalidate();

//		((TextView) findViewById(R.id.statusbar_life)).setText("Points: "+ i +"    Lives: 3");
//		i++;
	}
	@Override
	public void run()
	{
		if( paused )
		{
			// TODO what TODO?
		}
		else
		{
			handler.postDelayed(this, sleep);

			if ( simulation != null ) update(0.02f);
		}
	}

	
	/*
	 *	Game Controls
	 */
	// key controls
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		switch (keyCode)
		{
		case KeyEvent.KEYCODE_DPAD_DOWN:
			simulation.move(Spaceship.DIRECTION_DOWN);
			break;
		case KeyEvent.KEYCODE_DPAD_UP:
			simulation.move(Spaceship.DIRECTION_UP);
			break;
		case KeyEvent.KEYCODE_DPAD_LEFT:
			simulation.move(Spaceship.DIRECTION_LEFT);
			break;
		case KeyEvent.KEYCODE_DPAD_RIGHT:
			simulation.move(Spaceship.DIRECTION_RIGHT);
			break;
		case KeyEvent.KEYCODE_DPAD_CENTER:
		case KeyEvent.KEYCODE_SPACE:
			simulation.shot();
			break;
		case KeyEvent.KEYCODE_P:
			if (paused)
			{
				paused = false;
				SoundController.getReference().resumeBackgroundSound();
			}
			else
			{
				paused = true;
				SoundController.getReference().pauseBackgroundSound();
			}
			handler.post(this);
			break;
		case KeyEvent.KEYCODE_M:
			Log.d("NAVE", Stage.print()); // TODO DEBUG
			break;
		}
		return super.onKeyDown(keyCode, event);
	}

	// Touch controls
	private GestureDetector gestureDetector;
    OnTouchListener gestureListener;
    @Override
	public void onClick(View v)
    {
		simulation.shot();
	}
	class GestureControlling extends SimpleOnGestureListener
	{
		private static final int SWIPE_MIN_DISTANCE = 10;
	    private static final int SWIPE_MAX_OFF_PATH = 40;
	    private static final int SWIPE_THRESHOLD_VELOCITY = 5;

	    @Override
	    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
	    {
	        try
	        {
	        	if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
	            		&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
	            		&& Math.abs(e1.getY() - e2.getY()) < SWIPE_MAX_OFF_PATH)
	        	{
	            	simulation.move(Spaceship.DIRECTION_LEFT);
	            	return true;
	            }  
	            else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
	            		&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
	            		&& Math.abs(e1.getY() - e2.getY()) < SWIPE_MAX_OFF_PATH)
	            {	
	            	simulation.move(Spaceship.DIRECTION_RIGHT);
	            	return true;
	            }
	            
	            if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE
	            		&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
	            		&& Math.abs(e1.getX() - e2.getX()) < SWIPE_MAX_OFF_PATH)
	            {	
	            	simulation.move(Spaceship.DIRECTION_UP);
	            	return true;
	            }
	            else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE
	            		&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY
	            		&& Math.abs(e1.getX() - e2.getX()) < SWIPE_MAX_OFF_PATH)
	            {	
	            	simulation.move(Spaceship.DIRECTION_DOWN);
	            	return true;
	            }

	        }
	        catch (Exception e) {}
	        return false;
	    }
	}
}